﻿using System;
using System.Data;
using MySql.Data.Types;
using MySql.Simple.Mapper.Finders;

namespace MySql.Simple.Mapper
{
    /// <summary>
    /// Binds the contents of a <see cref="IDataReader"/> onto an object.
    /// </summary>
    public static class DataReaderBinder
    {
        public static T Bind<T>(IDataReader reader)
        {
            return (T) Bind(reader, typeof (T));
        }

        public static object Bind(IDataReader reader, Type type)
        {
            var result = type.GetConstructor(new Type[0]).Invoke(new object[0]);

            var properties = result.GetType().GetProperties();

            foreach (var property in properties)
            {
                var columnName = ColumnFinder.FindColumn(property);

                if (string.IsNullOrEmpty(columnName)) continue;

                var ordinal = reader.GetOrdinal(columnName);

                if (ordinal <= -1) continue;

                var value = reader[columnName];

                if (value == DBNull.Value)
                {
                    // nothing
                }
                else if (property.PropertyType.BaseType == typeof(Enum))
                {
                    var enumeration = Enum.Parse(property.PropertyType, value.ToString());

                    property.SetValue(result, enumeration, null);
                }
                else if (property.PropertyType == typeof(Boolean))
                {
                    var boolean  = Convert.ToInt16(value);

                    property.SetValue(result, boolean == 1, null);
                }
                else if (value.GetType() == typeof(MySqlDateTime))
                {
                    var date = (MySqlDateTime)value;

                    if (date.Year == 0) date = new MySqlDateTime(new DateTime(1, 1, 1));

                    property.SetValue(result, date.GetDateTime(), null);
                }
                else
                {
                    property.SetValue(result, value, null);
                }
            }

            return result;
        }
    }
}